package modulo9;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;

/**
 * Classe responsável por armazenar a integralização de um aluno.
 * 
 * Esta classe faz a leitura de um arquivo de integralização da Diretoria
 * acadêmica e por listar as disciplinas cursadas pelo aluno bem como
 * as principais informações dessas disciplinas atravez da classe Disciplina
 * Cursada
 *
 * @author Nícolas Riccieri Gardin Assumpção    Ra: 121245
 * @author Lucas Borges Moreira de Souza        Ra: 034126
 * @author Ivan Henrique Costa Petrin           Ra: 117300
 * @author Joseph Victoria Lorenzo V            Ra: 119651
 * @author Érick Machado Seolin                 Ra: 120891
 * @author Leonardo Gabriel Sousa Sorensen      Ra: 121096
 * 
 */
public class Integralizacao {
    private String raAluno;
    private int codigoCurso;
    private String anoCatalogo;
    private ArrayList disciplinas;
    private double cp;
    
    /**
     * Construtor da classe Integralizacao
     * <p>
     * Construtor recebe o nome do arquivo de integralização do aluno e recupera
     * as informações das disciplinas em objetos da classe DisciplinaCursada.
     * 
     * @param arquivo Nome do arquivo de integralização
     * @throws IOException Qualquer erro que aconteça de entrada e saída
     * @throws FileNotFoundException arquivo não encontrado
     * @throws IncorrectFileException arquivo não é uma integralização
     * 
     */
    public Integralizacao(String arquivo) throws IncorrectFileException, FileNotFoundException, IOException {
        //Buffer de leitura do arquivo
        BufferedReader in = new BufferedReader(new FileReader(arquivo));
        
        //variaveis do metodo
        this.disciplinas = new ArrayList();
        int curso;
        String ra,str="";
        
        //Procura o RA
        while (in.ready() && !str.contains("REGISTRO ACADEMICO:")) {
            //leitura da linha
            str = in.readLine();
        }
        //encontrou o RA
        if(str.contains("REGISTRO ACADEMICO:")){
            int local_ra = str.indexOf("REGISTRO ACADEMICO:");
            ra = str.substring(local_ra+20, local_ra+26);
           this.raAluno = ra;
        } else {//ERRO
            throw new IncorrectFileException();
        }
        
        
        //Procura curso
        while (in.ready() && !str.contains("CURSO:")) {
            //leitura da linha
            str = in.readLine();
        }
        //encontrou curso na integralizacao
        if(str.contains("CURSO:")){
            int local_curso = str.indexOf("CURSO:");
            curso = Integer.parseInt(str.substring(local_curso+6, local_curso+12).replace(" ", ""));
            this.codigoCurso = curso;
        } else {//ERRO
            throw new IncorrectFileException();
        }
        
        //Procura catalogo
        while (in.ready() && !str.contains("CATALOGO:")) {
            //leitura da linha
            str = in.readLine();
        }
        //encontrou curso na integralizacao
        if(str.contains("CATALOGO:")){
            int local_ano = str.indexOf("CATALOGO:");
            String ano = str.substring(local_ano+10, local_ano+14);
            this.anoCatalogo = ano;
        } else {//ERRO
            throw new IncorrectFileException();
        }
        
        //Procura CP
        while (in.ready() && !str.contains("_CP :")) {
            //leitura da linha
            str = in.readLine();
        }
        //encontrou CP
        if(str.contains("_CP :")){
            int local_cp = str.indexOf("_CP :");
            String cps = str.substring(local_cp+6, local_cp+12).replace(',', '.').replaceAll(" ","");
            this.cp = Double.parseDouble(cps);
        } else {//ERRO
            throw new IncorrectFileException();
        }
        
        //Procura inicio das disciplinas
        while (in.ready() && str.compareTo("  HISTORICO ATUAL:")!=0) {
            //leitura da linha
            str = in.readLine();
        }
        //inicia leitura das disciplinas
        if(str.compareTo("  HISTORICO ATUAL:")==0){
            str = in.readLine();
            //LEITURA DAS DISCIPLINAS
            while (in.ready() && str.length()>=37) {
                //PRIMEIRA COLUNA
                ProcessamentoLinha(str.substring(0,37));
                if(str.length() > 40){//se houver segunda coluna
                    //SEGUNDA COLUNA
                    ProcessamentoLinha(str.substring(40,77));
                }
                str = in.readLine();
            }
        } else {//ERRO
            throw new IncorrectFileException();
        }
        
        in.close();
    }
    
    /**
     * Retorna a quantidade de disciplinas da integralização
     * 
     * @return quantidade de disciplinas contidas na integralização
     */
    public int getQuantasDisciplinas(){
        return this.disciplinas.size();
    }
    
    /**
     * Retorna o ano do catálogo da integralização
     * 
     * @return ano do catálogo da integralização.
     */
    public String getAnoCatalogo(){
        return this.anoCatalogo;
    }
    
    /**
     * Retorna o Coeficiente de Progreção
     * 
     * @return coeficiente de progressão que indica a parte do curso já concluida.
     */
    public double getCP(){
        return this.cp;
    }

    /**
     * Retorna o código do curso do aluno.
     * 
     * @return código numérico do curso
     */
    public int getCodigoCurso() {
        return codigoCurso;
    }


    /**
     * Retorna as disciplinas cursadas
     * <p>
     * Classe retorna um objeto da classe ArrayList contendo objetos da 
     * classe DisciplinaCursada que representam as disciplinas da integralização
     * 
     * @return Lista de disciplinas cursadas pelo aluno
     */
    public Collection getDisciplinasCursadas() {
        return disciplinas;
    }
    
    /**
     * Retorna as disciplinas onde o aluno foi aprovado
     * <p>
     * Classe retorna um objeto da classe ArrayList contendo objetos da 
     * classe DisciplinaCursada que representam as disciplinas da integralização
     * que podem ser utilizadas em matérias nas quais elas são pré-requisito
     * 
     * @return Lista de disciplinas onde o aluno foi aprovado
     */
    public Collection getDisciplinasAprovadas(){
        ArrayList retorno = new ArrayList();
        DisciplinaCursada aux;
        for(int i = 0; i < this.disciplinas.size(); i++){
            aux = (DisciplinaCursada)(this.disciplinas.get(i));
            if(aux.IsCumprimento()){
                retorno.add(aux);
            }
        }
        return retorno;
    }
    
    /**
     * Retorna as disciplinas cursadas pelo aluno que são obrigatórias no curso
     * <p>
     * Classe retorna um objeto da classe ArrayList contendo objetos da 
     * classe DisciplinaCursada que representam as disciplinas da integralização
     * cursadas pelo aluno que são obrigatórias para a conclusão do 
     * curso indicado pela integralização
     * 
     * @return Lista de disciplinas obrigatórias cursadas pelo aluno
     */
    public Collection getDisciplinasObrigatoriasCursadas(){
        ArrayList retorno = new ArrayList();
        DisciplinaCursada aux;
        for(int i = 0; i < this.disciplinas.size(); i++){
            aux = (DisciplinaCursada)(this.disciplinas.get(i));
            if(aux.getAproveitamento().compareTo("OBRIGATORIA") == 0){ 
                retorno.add(aux);
            }
        }
        return retorno;
    }
    
    /**
     * Retorna as disciplinas cursadas pelo aluno que são eletivas
     * <p>
     * Classe retorna um objeto da classe ArrayList contendo objetos da 
     * classe DisciplinaCursada que representam as disciplinas da integralização
     * cursadas pelo aluno que são eletivas
     * 
     * @return Lista de disciplinas eletivas cursadas pelo aluno
     */
    public Collection getDisciplinasEletivasCursadas(){
        ArrayList retorno = new ArrayList();
        DisciplinaCursada aux;
        for(int i = 0; i < this.disciplinas.size(); i++){
            aux = (DisciplinaCursada)(this.disciplinas.get(i));
            if(aux.getAproveitamento().compareTo("ELETIVA")==0){
                retorno.add(aux);
            }
        }
        return retorno;
    }
    
    /**
     * Retorna as disciplinas cursadas pelo aluno que são extra-curriculares
     * <p>
     * Classe retorna um objeto da classe ArrayList contendo objetos da 
     * classe DisciplinaCursada que representam as disciplinas da integralização
     * cursadas pelo aluno que são extra-curriculares
     * 
     * @return Lista de disciplinas extra-curriculares cursadas pelo aluno
     */
    public Collection getDisciplinasExtraCurricularesCursadas(){
        ArrayList retorno = new ArrayList();
        DisciplinaCursada aux;
        for(int i = 0; i < this.disciplinas.size(); i++){
            aux = (DisciplinaCursada)(this.disciplinas.get(i));
            if(aux.getAproveitamento().compareTo("EXTRA-CURRICULAR")==0){
                retorno.add(aux);
            }
        }
        return retorno;
    }    
    
    /**
     * Retorna disciplinas cursadas submetidas a um filtro
     * 
     * @param obrigatorias verdadeiro para retorno conter 
     * disciplinas obrigatorias e falso para excluí-las
     * @param eletivas verdadeiro para retorno conter disciplinas eletivas e 
     * falso para excluí-las
     * @param extra_curriculares verdadeiro para retorno conter 
     * disciplinas extra-curriculares e falso para excluí-las 
     * @param aprovado verdadeiro para retornar só as aprovadas e 
     * falso para incluir aprovadas e reprovadas
     * @return Lista de disciplinas após submetidas ao filtro
     */
    public Collection getDisciplinasFiltradas(boolean obrigatorias, 
                    boolean eletivas, boolean extra_curriculares, 
                    boolean aprovado){
        ArrayList retorno = new ArrayList();
        if(obrigatorias){
            retorno.addAll(this.getDisciplinasObrigatoriasCursadas());
        }
        if(eletivas){
            retorno.addAll(this.getDisciplinasEletivasCursadas());
        }
        if(extra_curriculares){
            retorno.addAll(this.getDisciplinasExtraCurricularesCursadas());
        }
     
        if(aprovado){
            DisciplinaCursada aux;
            for(int i = 0; i < retorno.size(); i++){
                aux = (DisciplinaCursada)(retorno.get(i));
                if(!aux.IsCumprimento()){
                    retorno.remove(i);
                    i--;
                }
            }
        }
        return retorno;
    }
    
    /**
     * Retorna disciplina em uma posição específica da lista
     * 
     * @param i posição da disciplina a ser retornada
     * @return disciplina na posição escolhida da lista
     */
    public DisciplinaCursada getDisciplina(int i){
        return (DisciplinaCursada)(this.disciplinas.get(i));
    }
    
    /**
     * Acrescenta uma nova disciplina na lista.
     * 
     * @param l linha completa da integralização no formato da dac
     * @param m sigla da disciplina
     * @param t turma
     * @param c quantidade de créditos
     * @param a aproveitamento da disciplina
     * @param cat categoria
     * @param n nota
     * @param ch carga horária
     * @param ca código de aprovação
     * @param p período
     */
    private void adicionarDisciplina(String l, String m, String t, int c, char a,
                            char cat, double n, int ch, int ca, String p){
        this.disciplinas.add(new DisciplinaCursada(l,m,t,c,a,cat,n,ch,ca,p));
    }

    /**
     * Retorna ra do aluno ao qual a integralização pertence
     * 
     * @return ra do aluno
     */
    public String getRaAluno() {
        return raAluno;
    }

    
    /**
     * Recebe uma linha no formato da DAC, separa conteudo da linha e 
     * acrescenta a nova disciplina
     * 
     * @param str linha de disciplina no formato da DAC
     */
    private final void ProcessamentoLinha(String str){
        int creditos,cargaHoraria,codigoAprovacao;
        String materia, turma,periodo;
        char aproveitamento,categoria;
        double nota;
        
        materia = str.substring(2,7);
        turma = str.substring(8,11);
        creditos = Integer.parseInt(str.substring(12,14));
        aproveitamento = str.charAt(15);
        categoria = str.charAt(17);
        
         //caso nao tenha nota coloca -1
        if((str.substring(19,23)).compareTo(" ---")==0){ 
            nota = -1.0;
        }
        else{
            nota = Double.parseDouble(str.substring(19,23).replaceAll(" ", "").replaceAll(",", "."));
        }
        cargaHoraria = Integer.parseInt(str.substring(24,27).replaceAll(" ", ""));
        codigoAprovacao = Integer.parseInt(str.substring(28,30).replaceAll(" ", ""));
        periodo = str.substring(31,37);
        
        //Inclui nova disciplina
        this.adicionarDisciplina(str.substring(2,37),materia, turma, creditos, 
                                aproveitamento, categoria, nota, cargaHoraria, 
                                codigoAprovacao, periodo);
    }
}
